package com.codebattery.service;


import com.alibaba.nacos.client.utils.StringUtils;
import com.codebattery.domain.entity.*;
import com.codebattery.domain.model.*;
import com.codebattery.mapper.BaseMapper;
import com.codebattery.repository.GoodsMapper;
import com.codebattery.util.EsUtil;
import com.codebattery.util.OssUtil;
import com.codebattery.util.StringReplacerUtil;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class GoodsService extends MyBatisBaseServiceImpl<Goods, Integer> {

    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private GoodsPicService goodsPicService;
    @Resource
    private GoodsAttrService goodsAttrService;
    @Resource
    private GoodsAttrValueService goodsAttrValueService;
    @Resource
    private ShopService shopService;
    @Resource
    private EsUtil esUtil;

    @Override
    protected BaseMapper<Goods, Integer> mapper() {
        return goodsMapper;
    }

    /**
     * 获取商品
     *
     * @param goodsId
     * @return
     */
    public Goods getGoods(Integer goodsId){
        Goods goods = this.selectByPrimaryKey(goodsId);

        Optional.ofNullable(goods).ifPresent(g -> {
            Shop shop = this.shopService.selectByPrimaryKey(g.getShopId());
            goods.setShop(shop);
        });
        return goods;
    }

    /**
     * 查看商品详情
     *
     * @param goodId
     * @return
     */
    public GoodsInfo detail(Integer goodId) {

        GoodsInfo info = new GoodsInfo();
        Goods goods = goodsMapper.selectByPrimaryKey(goodId);

        info.setGoodsId(goodId);
        info.setTitle(goods.getName());
        info.setPrice(String.valueOf(goods.getPrice()));
        info.setGoodsDetail(goods.getDescript());
        info.setRemarksNum("100");

        /*
         * 商店
         */
        Shop shop = shopService.selectByPrimaryKey(goods.getShopId());
        GoodsInfo.Shop shopInfo = new GoodsInfo.Shop();
        shopInfo.setName(shop.getName());
        shopInfo.setIntro(shop.getIntroduction());
        shopInfo.setImg(shop.getImage());
        info.setShop(shopInfo);

        List<GoodsPic> goodsPics = goodsPicService.getGoodsPic(goodId);
        List<String> goodsImgs = goodsPics.stream()
                .map(pic -> pic.getPicUrl()).collect(Collectors.toList());
        info.setGoodsImg(goodsImgs);

        /*
         * 套餐
         */
        List<GoodsAttr> goodsAttrs = goodsAttrService.selectGoodsAttr(goodId);
        if(goodsAttrs!=null) {
            GoodsInfo.Meal [][] meals = new GoodsInfo.Meal[goodsAttrs.size()][];
            for(int i=0;i<goodsAttrs.size();i++ ){
                GoodsAttr attr = goodsAttrs.get(i);
                if(attr.getValues()!=null){
                    GoodsInfo.Meal [] meal = new GoodsInfo.Meal[attr.getValues().size()];

                    for(int j=0; j<attr.getValues().size(); j++){
                        GoodsAttrValue value = attr.getValues().get(j);
                        GoodsInfo.Meal mealItem = new GoodsInfo.Meal();
                        mealItem.setIntro(value.getName());
                        mealItem.setPrice(String.valueOf(value.getPrice()));
                        mealItem.setImg(value.getImage());
                        meal[j] = mealItem;
                    }

                    meals[i] = meal;
                }
            }

            info.setSetMeal(meals);
        }

        /*
         * 搜索商店的其他热销商品
         */
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.query(QueryBuilders.boolQuery()
                    .should(QueryBuilders.matchQuery("shopId", goods.getShopId()))
            );
        List<GoodsSearchInfo> shopGoodsSearchInfos = esUtil.search("goods", searchSourceBuilder, GoodsSearchInfo.class);

        Optional.ofNullable(shopGoodsSearchInfos).ifPresent(infos ->{
            List<GoodsInfo.HotGoodsInfo> hotGoodsInfos = infos.stream().map(searchInfo -> {
                return new GoodsInfo.HotGoodsInfo(
                        Integer.valueOf(searchInfo.getId()),
                        searchInfo.getIntro(),
                        searchInfo.getImg(),
                        searchInfo.getPrice(),
                        searchInfo.getSales()
                );
            }).collect(Collectors.toList());

            info.setHot(hotGoodsInfos);
        });

        return info;
    }

    public GoodsListSearchInfo seach(String query) {

        GoodsListSearchInfo goodsListSearchInfo = new GoodsListSearchInfo();

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        if(org.apache.commons.lang.StringUtils.isNotEmpty(query)){
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            searchSourceBuilder.query(boolQueryBuilder);
            if(org.apache.commons.lang.StringUtils.isNumeric(query)){
                boolQueryBuilder.should(QueryBuilders.matchQuery("id", query).analyzer("ik_max_word"));
            }
            boolQueryBuilder.should(QueryBuilders.matchQuery("intro", query).analyzer("ik_max_word"));
//            boolQueryBuilder.should(QueryBuilders.matchQuery("keyword", query).analyzer("ik_max_word"));
        }
//                .from((filter.getPageNum() - 1) * filter.getPageSize())
//                .size(filter.getPageSize());

        List<GoodsSearchInfo> goodsList = esUtil.search("goods", searchSourceBuilder, GoodsSearchInfo.class);
        goodsListSearchInfo.setGoodsInfos(goodsList);


        /*
         * 查询销量最大的5个商品
         */
        SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();


        searchSourceBuilder2.query(QueryBuilders.matchAllQuery()
              ).size(5)
                .sort("sales", SortOrder.DESC);

        List<GoodsSearchInfo> recommends = esUtil.search("goods", searchSourceBuilder2, GoodsSearchInfo.class);

        goodsListSearchInfo.setRecommendGoodsInfos(recommends);

        return goodsListSearchInfo;
    }

    public List<SeckillGoodsInfo> listSeckillGoods() {
        List<SeckillGoodsInfo> seckillGoodsInfos = goodsMapper.listSekillGoods();
        return  seckillGoodsInfos;
    }

    /**
     * 添加商品
     *
     * @param product
     */
    public void addGoods(StoreProduct product) throws Exception {

        /*
         * 同步shop信息
         */
        Optional.of(product.getStore()).ifPresent(shopInfo -> {
            try {
                Shop shop = shopService.selectByPrimaryKey(shopInfo.getId());
                if(shop!=null){
                            shop.setName(shopInfo.getName());
                            shop.setNum(shopInfo.getNum());
                            shop.setIntroduction(shopInfo.getIntroduction());
                            shop.setPhone(shopInfo.getPhone());
                            shop.setAddress(shopInfo.getAddress());
                            shop.setDetailedAddress(shopInfo.getDetailedAddress());
                            shop.setImage(createImg(shopInfo.getImage()));
                            shop.setLatitude(shopInfo.getLatitude());
                            shop.setLongitude(shopInfo.getLongitude());
                            shop.setValidTime(shopInfo.getValidTime());
                            shop.setDayTime(shopInfo.getDayTime());
                            shop.setAddTime(shopInfo.getAddTime());
                            shop.setDayTimeEnd(shopInfo.getDayTimeEnd());
                            shop.setDayTimeStart(shopInfo.getDayTimeStart());
                            shop.setValidTimeEnd(shopInfo.getValidTimeEnd());
                            shop.setValidTimeStart(shopInfo.getValidTimeStart());

                    shopService.updateByPrimaryKey(shop);
                } else {
                        shop = new Shop(
                            shopInfo.getId(),
                            shopInfo.getName(),
                            shopInfo.getNum(),
                            shopInfo.getIntroduction(),
                            shopInfo.getPhone(),
                            shopInfo.getAddress(),
                            shopInfo.getDetailedAddress(),
                            createImg(shopInfo.getImage()),
                            shopInfo.getLatitude(),
                            shopInfo.getLongitude(),
                            shopInfo.getValidTime(),
                            shopInfo.getDayTime(),
                            shopInfo.getAddTime(),
                            null,
                            null,
                            shopInfo.getDayTimeEnd(),
                            shopInfo.getDayTimeStart(),
                            shopInfo.getValidTimeEnd(),
                            shopInfo.getValidTimeStart()
                    );
                    shopService.insert(shop);
                }
            } catch (Exception e) {
                log.error("上传商店图片出错, url={}", shopInfo.getImage());
            }
        });

        /*
         * 替换description的图片上传到oss
         */
        String newDescription = product.getDescription();
        if (StringUtils.isNotEmpty(product.getDescription())) {
            newDescription = StringReplacerUtil.replace(product.getDescription(), Pattern.compile("src=['\"]([^'\"]+)['\"]"), matcher -> {

                String group = matcher.group();
                String localUrl = group.substring(group.indexOf("\"") + 1, group.lastIndexOf("\""));


                String fileName = localUrl.substring(localUrl.lastIndexOf("/") + 1, localUrl.length());
                try {
                    OssUtil.uploadObjectByInputStream(new URL(localUrl).openStream(),
                            fileName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                String fileUrl = OssUtil.getFileUrl(fileName, 3600 * 1000);

                log.info("上传描述图片{}成功", fileName);
                return "src=\"" + fileUrl + "\"";
            });
        }

        Goods goods = goodsMapper.selectByProductId(product.getId());
        if (goods != null) {
            goods.setBarCode(product.getBarCode());
            goods.setName(product.getStoreName());
            goods.setKeyword(product.getKeyword());
            goods.setSupplierId(product.getMerId());
            goods.setPrice(product.getPrice());
            goods.setDescript(newDescription);
            goods.setShopId(product.getStore().getId());
            goods.setSales(product.getSales());

            this.updateByPrimaryKey(goods);

            /*
             * 删除旧的商品属性，并创建新的商品属性
             */
            final Integer goodsId= goods.getId();
            clearGoodAttr(goodsId);
            createGoodsAttr(product, goodsId);

        } else {
            String img = createImg(product.getImage());
            goods = new Goods(
                    null,
                    product.getId(),
                    product.getStore().getId(),
                    product.getBarCode(),
                    product.getStoreName(),
                    product.getKeyword(),
                    product.getBarCode(),
                    0,
                    img,
                    (short) 0,
                    (short) 0,
                    (short) 0,
                    product.getMerId(),
                    product.getPrice(),
                    product.getOtPrice(),
                    new BigDecimal(0),
                    (byte) 1,
                    (byte) 1,
                    0.0d,
                    0.0d,
                    0.0d,
                    0.0d,
                    null,
                    new Date(),
                    0,
                    newDescription,
                    new Date(),
                    (byte)product.getIsSeckill().byteValue(),
                    new Date(),
                    product.getSales(),
                    null
            );
            int result = this.insert(goods);

            if (result > 0) {
                /*
                 * 创建轮播图片
                 */
                createImgs(goods.getId(), product.getSliderImage(), false);
            }

            final Integer goodsId = goods.getId();

            /*
             * 添加商品属性
             */
            clearGoodAttr(goodsId);
            createGoodsAttr(product, goodsId);
        }

        GoodsSearchInfo goodsSearchInfo = new GoodsSearchInfo(
                String.valueOf(goods.getId()),
                goods.getName(),
                goods.getImg(),
                String.valueOf(goods.getPrice()),
                "100",
                String.valueOf(product.getStore().getId()),
                product.getStore().getName(),
                goods.getSales()
        );

        esUtil.insertOrUpdateOne("goods",
                new EsEntity<GoodsSearchInfo>(String.valueOf(goods.getId()), goodsSearchInfo));

    }

    private void clearGoodAttr(Integer goodsId) {
        List<GoodsAttr> goodsAttrs = goodsAttrService.selectGoodsAttr(goodsId);
        for(GoodsAttr goodsAttr : goodsAttrs){
            goodsAttrService.deleteByPrimaryKey(goodsAttr.getId());
            if(goodsAttr.getValues()!=null) {
                for(GoodsAttrValue value : goodsAttr.getValues()){
                    goodsAttrValueService.deleteByPrimaryKey(value.getId());
                }
            }
        }
    }

    private void createGoodsAttr(StoreProduct product, Integer goodsId) {
        if(product.getAttrs()!=null && !product.getAttrs().isEmpty()){
            List<GoodsAttr> goodsAttrs = product.getAttrs().stream().map(attr -> {
                GoodsAttr goodsAttr = new GoodsAttr(
                        attr.getId(),
                        goodsId,
                        attr.getAttrName(),
                        null
                        );

                List<StoreProduct.GoodsAttr.GoodsAttrValue> values = attr.getValues();


                if(values !=null && !values.isEmpty()){
                    List<GoodsAttrValue> goodsAttrValues = values.stream().map(value -> {
                        String attrImg = null;
                        try {
                            attrImg = this.createImg(value.getImage());
                        } catch (Exception e) {
                            log.error("上传属性图片失败, url={}", value.getImage());
                        }
                        return new GoodsAttrValue(
                                value.getId(),
                                value.getSuk(),
                                value.getValue(),
                                value.getStock(),
                                value.getSales(),
                                value.getPrice(),
                                attrImg,
                                value.getCost(),
                                null
                        );
                    }).collect(Collectors.toList());

                    goodsAttr.setValues(goodsAttrValues);
                }

                return goodsAttr;
            }).collect(Collectors.toList());


            for (GoodsAttr attr : goodsAttrs) {
                goodsAttrService.insert(attr);

                if(attr.getValues()!=null && !attr.getValues().isEmpty()){
                    for(GoodsAttrValue attrValue : attr.getValues()){
                        attrValue.setAttrId(attr.getId());
                        goodsAttrValueService.insert(attrValue);
                    }
                }
            }
        }
    }

    private String createImg(String imageStr) throws Exception {
        String fileName = imageStr.substring(imageStr.lastIndexOf("/") + 1, imageStr.length());
        OssUtil.uploadObjectByInputStream(new URL(imageStr).openStream(),
                fileName);
        String fileUrl = OssUtil.getFileUrl(fileName, 3600 * 1000);
        return  fileUrl;
    }

    private void createImgs(int goodId, String imageStr, boolean isMaster) throws Exception {
        if (StringUtils.isNotEmpty(imageStr)) {
            String[] imgUrls = imageStr.split(",");

            for (String url : imgUrls) {
                String fileName = url.substring(url.lastIndexOf("/") + 1, url.length());
                OssUtil.uploadObjectByInputStream(new URL(url).openStream(),
                        fileName);
                String fileUrl = OssUtil.getFileUrl(fileName, 3600 * 1000);
                GoodsPic pic = new GoodsPic(
                        null,
                        goodId,
                        null,
                        fileUrl,
                        isMaster == true ? (byte) 1 : (byte) 0,
                        (byte) 0,
                        (byte) 0,
                        new Date()
                );
                goodsPicService.insert(pic);
            }
        }
    }
}
